/**
 * Copyright 2010 Balaji Thennarangam.
 */
package com.kathez.dao;

import com.kathez.CRUDOperataionType;
import com.kathez.Root;
import com.kathez.entity.AbstractKathezEntity;
import com.kathez.entity.DAOOperable;
import com.kathez.exceptions.KathezRuntimeException;

/**
 * Abstract implementation of {@link IKathezDao}.
 * All DAO classes must extend this abstract class.
 * @author Balaji T
 *
 */
public abstract class AbstractKathezDao extends Root implements IKathezDao {

	/* (non-Javadoc)
	 * @see com.kathez.dao.IKathezDao#doDataOperation(com.kathez.entity.KathezEntity, com.kathez.CRUDOperataionType)
	 */
	@Override
	public final DAOResult doDataOperation(DAOOperable entityObject,
			CRUDOperataionType operationType) {
		DAOResult returnObject = null;
		if(entityObject != null && operationType!= null){
			returnObject = doDataOperation((AbstractKathezEntity)entityObject,operationType);
			if(returnObject != null){
				operationType = CRUDOperataionType.DELETE;
				if(returnObject.getDAOOpsType() != operationType){
					rollBack((AbstractKathezEntity)entityObject, returnObject.getDAOOpsType());
					throw new KathezRuntimeException("Invalid DAO Result type returned. Expected DAO Result "+operationType+", Actual DAO Result "+returnObject.getDAOOpsType());
				}
				returnObject = postDBOperation((AbstractKathezEntity)entityObject,operationType,returnObject);
			}
			commit(null, null);
		}
		return returnObject;
	}	

	protected abstract DAOResult doDataOperation(AbstractKathezEntity entityObject,
			CRUDOperataionType operationType);
	protected abstract void rollBack(AbstractKathezEntity entityObject, CRUDOperataionType operationType);
	protected abstract void commit(AbstractKathezEntity entityObject, CRUDOperataionType opearationType);

	
	private DAOResult postDBOperation(AbstractKathezEntity entityObject,CRUDOperataionType operationType,DAOResult dbOpResultObject){
		
		if(dbOpResultObject != null){
			CRUDOperataionType opsType = dbOpResultObject.getDAOOpsType();
			switch(opsType){
				case ADD:
					entityObject.setDataOpsSuccess(((DAOInsertResult)dbOpResultObject).isInsertSuccess());
					break;
				case UPDATE:
					entityObject.setDataOpsSuccess(((DAOUpdateResult)dbOpResultObject).isUpdateSuccess());
					break;
				case DELETE:
					entityObject.setDataOpsSuccess(((DAODeleteResult)dbOpResultObject).isDeleteSuccess());
					break;
				case FETCH:
					entityObject.setDataOpsSuccess(((DAOFetchResult)dbOpResultObject).isFetchSuccess());
					break;				
			}
		}
		return dbOpResultObject;
	}

}
